package org.fast.develop.logicflow.rest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import org.fast.develop.logicflow.core.meta.exception.LogicFlowMetaException;
import org.fast.develop.logicflow.management.bo.LogicModelBo;
import org.fast.develop.logicflow.management.bo.LogicModelDetailBo;
import org.fast.develop.logicflow.management.service.LogicModelService;
import org.fast.develop.logicflow.repository.domain.deployment.LogicDeployment;
import org.fast.develop.logicflow.repository.domain.model.LogicModel;
import org.fast.develop.logicflow.rest.dto.SaveModelDto;
import org.fast.develop.logicflow.rest.dto.TestModelReqDto;
import org.fast.develop.logicflow.rest.dto.TestModelResDto;
import org.fast.develop.logicflow.rest.dto.condition.LogicModelCondition;
import org.fast.develop.logicflow.rest.execute.LogicFlowExecutorEnhance;
import org.fast.develop.logicflow.rest.util.VoUtil;
import org.fast.develop.logicflow.runtime.exception.LogicFlowException;
import org.fast.develop.logicflow.runtime.exception.LogicFlowRuntimeException;
import org.fast.develop.logicflow.runtime.instance.LogicFlowInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 莫寅
 * @createTime 2022-12-22 01:10
 * @desc：
 */
@RestController
@RequestMapping("logic/model")
public class LogicModelController {

    @Autowired
    private LogicModelService logicModelService;

    @Autowired
    private LogicFlowExecutorEnhance logicFlowExecutorEnhance;


    @GetMapping("{id}")
    public ResponseEntity<LogicModelDetailBo> get(@PathVariable(name = "id") String id) {
        return VoUtil.setSuccessResult(
                logicModelService.get(id)
        );
    }


    @GetMapping
    public ResponseEntity<List<? extends LogicModel>> search(LogicModelCondition logicModelCondition) {
        LogicModelBo logicModelBo = BeanUtil.copyProperties(logicModelCondition, LogicModelBo.class);
        return VoUtil.setSuccessResult(
                logicModelService.getList(logicModelBo)
        );
    }

    @PostMapping
    public ResponseEntity<LogicModel> create(@RequestBody SaveModelDto saveModelDto) {
        LogicModel logicModel = logicModelService.createModel()
                .name(saveModelDto.getName())
                .key(saveModelDto.getKey())
                .category(saveModelDto.getCategory())
                .create();

        return VoUtil.setSuccessResult(logicModel);
    }


    /**
     * 修改
     *
     * @param id
     * @param saveModelDto
     * @return
     */
    @PutMapping("{id}")
    public ResponseEntity<LogicModel> update(@PathVariable(name = "id") String id, @RequestBody SaveModelDto saveModelDto) {
        LogicModel logicModel = logicModelService.updateModel()
                .id(id)
                .name(saveModelDto.getName())
                .key(saveModelDto.getKey())
                .category(saveModelDto.getCategory())
                .update();

        return VoUtil.setSuccessResult(logicModel);
    }

    /**
     * 保存schema
     *
     * @param id
     * @param schema
     * @return
     */
    @PutMapping("{id}/schema")
    public ResponseEntity saveSchema(@PathVariable(name = "id") String id, @RequestBody Map schema) {
        logicModelService.saveSchema(id, JSONUtil.toJsonStr(schema));

        return VoUtil.getSuccessResult();
    }


    @GetMapping("{id}/schema")
    public ResponseEntity<Map> getSchema(@PathVariable(name = "id") String id) {
        String schema = logicModelService.getSchema(id);
        return VoUtil.setSuccessResult(
                JSONUtil.toBean(schema, Map.class)
        );
    }

    /**
     * 发布
     *
     * @param id
     * @return
     */
    @PostMapping("{id}/deploy")
    public ResponseEntity<LogicDeployment> deploy(@PathVariable(name = "id") String id) {
        LogicDeployment logicDeployment = logicModelService.deploy(id);

        return VoUtil.setSuccessResult(logicDeployment);
    }


    /**
     * 删除
     *
     * @param id
     * @return
     */
    @DeleteMapping("{id}")
    public ResponseEntity delete(@PathVariable(name = "id") String id) {
        logicModelService.delete(id);

        return VoUtil.getSuccessResult();
    }

    @PostMapping("{id}/test")
    public ResponseEntity<TestModelResDto> test(@PathVariable(name = "id") String id, @RequestBody TestModelReqDto testModelDto) {
        try {
            LogicFlowInstance logicFlowInstance = logicFlowExecutorEnhance.execute(id, Objects.isNull(testModelDto.getMap()) ? new HashMap() : testModelDto.getMap());
            return VoUtil.setSuccessResult(
                    new TestModelResDto()
                            .setMap(testModelDto.getMap())
                            .setResult(logicFlowInstance.getVariables())
                            .setLogsObj(logicFlowInstance.getLogicFlowMonitor().getExecuteLogs())
            );
        } catch (LogicFlowRuntimeException e) {
            Map result = new HashMap<>();
            result.put("error", e.getMessage());
            return VoUtil.setSuccessResult(
                    new TestModelResDto()
                            .setMap(testModelDto.getMap())
                            .setResult(result)
                            .setLogsObj(e.getLogicFlowMonitor().getExecuteLogs())
            );

        } catch (LogicFlowException | LogicFlowMetaException e) {
            Map result = new HashMap<>();
            result.put("error", e.getMessage());
            return VoUtil.setSuccessResult(
                    new TestModelResDto()
                            .setMap(testModelDto.getMap())
                            .setResult(result)
            );
        }
    }
}
